#include <iostream>
#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc.hpp"
#include "stdlib.h"

class ColorDetector
{
private:
//    储存结果的二值图像
    cv::Mat result;
//    目标颜色
    cv::Vec3b target;
//    允许的最小差距
    int maxDistance;

public:
    ColorDetector():maxDistance(100),target(0,0,0) {}
//    计算两个颜色之间的城区距离
    int GetColorDistance(const cv::Vec3b &color1\
                         ,const cv::Vec3b &color2)const{
        return abs(color1[0] - color2[0])\
                +abs(color1[1] - color2[1])\
                +abs(color1[2] - color2[2]);
    }
//    计算与目标颜色的差距
    int GetDistanceToTargetColor(const cv::Vec3b &color) const{
        return GetColorDistance(color,target);
    }

    cv::Mat Process(const cv::Mat &img){
//        切记要为result分配大小
        result.create(img.size(),img.type());
        cv::Mat_<cv::Vec3b>::const_iterator it_begin = img.begin<cv::Vec3b>();
        cv::Mat_<cv::Vec3b>::const_iterator it_end = img.end<cv::Vec3b>();
        cv::Mat_<uchar>::iterator it_out = result.begin<uchar>();
        for(; it_begin != it_end; ++it_begin,++it_out){
            if(GetDistanceToTargetColor(*it_begin) <= maxDistance){
//                把目标颜色用一个新的颜色值标记，比如255
                *it_out = 255;
            }else{
//                把非目标颜色用一个新的颜色值标记，比如0
                *it_out = 0;
            }
        }
        return result;
    }
    int getMaxDistance() const{
        return maxDistance;
    }
    void setMaxDistance(int value){
        if(value < 0){
            value = 0;
        }
        maxDistance = value;
    }
    cv::Vec3b getTarget() const{
        return target;
    }
    void setTargetColor(const cv::Vec3b &value){
        target = value;
    }
    void setTargetColor(uchar blue,uchar green,uchar red){
        target = cv::Vec3b(blue,green,red);
    }
};

void test_color_detection_algorithm()
{
//    创建图像处理器对象
    ColorDetector colorDetector;
//    读取输入图像
    cv::Mat src1 = cv::imread("/home/iroan-ubuntu16/Project/Coding/GraduationProjectCode/src2.jpg");
    if(src1.empty()){
        return ;
    }
    cv::imshow("src1",src1);
    cv::imwrite("2017-03-11src1.jpg",src1);
//    设置输入参数
//    方法一
//    colorDetector.setTargetColor(230,190,120);
//    方法二
    colorDetector.setTargetColor(cv::Vec3b(230,190,120));

//    处理图像并显示结果
    cv::Mat res = colorDetector.Process(src1);
    cv::imshow("Process src1",res);
    cv::imwrite("2017-03-11Process src1.jpg",res);
    cv::waitKey(0);
}

void test_split()
{
    cv::Mat src1 = cv::imread("/home/iroan-ubuntu16/Project/Coding/GraduationProjectCode/src1.jpg");
    if(src1.empty()){
        std::cout<<"This img is empty"<<std::endl;
    }
    std::vector<cv::Mat> planes;

    cv::imshow("src1",src1);
    cv::split(src1,planes);
    cv::imshow("planes[0]",planes[0]);
    cv::imshow("planes[1]",planes[1]);
    cv::imshow("planes[2]",planes[2]);

    cv::waitKey(0);
}

class Controller
{
private:
//    包含算法的类
    ColorDetector * cdetect;
//    保存被处理的图像
    cv::Mat img;
//    保存结果图像
    cv::Mat res;
public:
    Controller() {
//        建立程序
        cdetect = new ColorDetector();
    }
//    设置颜色差距的阈值
    void setColorDistanceThreshold(int distance){
        cdetect->setMaxDistance(distance);
    }
//    获取颜色差距的阈值
    int getColorDistanceThreshold()const{
        return cdetect->getMaxDistance();
    }
//    设置被检测的颜色
    void setTargetColor(uchar red,uchar green,uchar blue){
        cdetect->setTargetColor(blue,green,red);
    }
//    获取被检测的颜色
    void getTargetColor(uchar &red,uchar &green,uchar &blue){
        cv::Vec3b color = cdetect->getTarget();
        red = color[2];
        green = color[1];
        blue = color[0];
    }
//    设置输入图像
    bool setInputImage(std::string file_name){
        img = cv::imread(file_name);
        return !img.empty();
    }
    const cv::Mat getInputImage()const{
        return img;
    }
//    执行图像处理
    void process(){
        res = cdetect->Process(img);
    }
//    获取图像经过处理的结果
    const cv::Mat getResultImage()const{
        return res;
    }
    ~Controller(){
        delete cdetect;
    }
};
void test_control_pattern()
{
    Controller control;
    control.setInputImage("/home/iroan-ubuntu16/Pictures/pic/src1.jpg");
    control.setColorDistanceThreshold(100);
    control.process();
    cv::Mat src = cv::imread("/home/iroan-ubuntu16/Pictures/pic/src1.jpg");
    cv::Mat res = control.getResultImage();

    cv::imshow("原图",src);
    cv::imshow("处理结果",res);

    cv::imwrite("2017-03-14src.jpg",src);
    cv::imwrite("2017-03-14res.jpg",res);
    cv::waitKey(0);
}

int main(){
//    test_color_detection_algorithm();
//    test_split();
    test_control_pattern();
    return 0;
}

